/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package workers;

import entities.Statement;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.Singleton;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.apache.log4j.Logger;
import org.joda.time.LocalDate;
import org.joda.time.Period;
import preferences.Preferences;
import session.StatementFacade;
import workers.statements.beans.CCStatementCSV;

/**
 *
 * @author bsmith
 */
@Singleton(name = "StatementsWorker")
@Local
public class StatementsWorkerImpl implements StatementsWorker {

    Logger logger = Logger.getLogger(StatementsWorkerImpl.class);
    @EJB
    private StatementFacade ejbStatementsFacade;
    @EJB
    private Preferences preferences;

    @Override
    @PostConstruct
    public void startup() {
        logger.info("Started Statements Worker ...");
    }

    public void setPreferences(Preferences preferences) {
        this.preferences = preferences;
    }
    
    @Override
    public List<Statement> lookupStatements(CCStatementCSV statementCSVItem) throws Exception {
        EntityManager em = ejbStatementsFacade.getEntityManager();
        Query statementsQuery = em.createNamedQuery("Statement.findByAllFields");

        statementsQuery.setParameter("type", statementCSVItem.getType());
        statementsQuery.setParameter("amount", Statement.formatAmount(statementCSVItem.getAmount()));
        statementsQuery.setParameter("balance", Statement.formatBalance(statementCSVItem.getBalance()));
        statementsQuery.setParameter("date", Statement.formatDate(statementCSVItem.getDate()));
        statementsQuery.setParameter("merchantTxt", statementCSVItem.getMerchant());
        List<Statement> statements = statementsQuery.getResultList();
        return statements;
    }

    @Override
    public List<Date> lookupFirstDate() {// throws Exception {
        EntityManager em = ejbStatementsFacade.getEntityManager();
        Query statementsQuery = em.createNamedQuery("Statement.findEarliestDates");

        List<Date> dates = statementsQuery.getResultList();
        return dates;
    }
    
    @Override
    public LocalDate determineStatementNumberDate(LocalDate transactionDate) {
        if (transactionDate.getDayOfMonth() < preferences.getStatementStartMonthDay()) { 
            return transactionDate.minusMonths(1).withDayOfMonth(preferences.getStatementStartMonthDay());
        } else {
            return transactionDate.withDayOfMonth(preferences.getStatementStartMonthDay());
        }
    }

    
    @Override
    public int determineStatementNumber(LocalDate firstTransactionDate, LocalDate thisTransactionDate) {
        LocalDate firstTransactionStatementDate = determineStatementNumberDate(firstTransactionDate);
        LocalDate thisTransactionStatementDate = determineStatementNumberDate(thisTransactionDate);

        int firstTransactionStatementDateMonthDay = firstTransactionStatementDate.getDayOfMonth();
        int thisTransactionStatementDateMonthDay = thisTransactionStatementDate.getDayOfMonth();
        
        if (firstTransactionStatementDateMonthDay != preferences.getStatementStartMonthDay()) {
            throw new IllegalArgumentException("firstTransactionStatentDate Day is incorrect - should be getStatementStartMonthDay():" + preferences.getStatementStartMonthDay()+", but its:"+firstTransactionStatementDateMonthDay);
        }
        if (thisTransactionStatementDateMonthDay != preferences.getStatementStartMonthDay()) {
            throw new IllegalArgumentException("statementNumberDate Day is incorrect - should be getStatementStartMonthDay():" + preferences.getStatementStartMonthDay()+", but its:"+thisTransactionStatementDateMonthDay);
        }
        if (thisTransactionStatementDate.isBefore(firstTransactionStatementDate)) {
            throw new IllegalArgumentException("thisTransactionDate: "+thisTransactionDate+" is before firstTransactionDate: "+firstTransactionDate);
        }
        int numberMonthsDiff = calDiffByMonth(firstTransactionStatementDate, thisTransactionStatementDate);
        return numberMonthsDiff+1;  // +1 as if in same month then first statment is 1
    }

    
    private int calDiffByMonth(LocalDate localDate1, LocalDate localDate2) {
        Period period = new Period(localDate1,localDate2);
        return period.getYears() * 12 + period.getMonths();
    }
}
